package com.xiashitech.agent.instrumentation.base.context;

import io.opentelemetry.javaagent.shaded.io.opentelemetry.context.ContextKey;

import javax.annotation.Nullable;
import java.util.Arrays;

public class ReentryArrayBasedContext implements XSContext {
    private static final XSContext ROOT = new ReentryArrayBasedContext(new Object[0]);

    static XSContext root() {
        return ROOT;
    }
    private final Object[] entries;
    private ReentryArrayBasedContext(Object[] entries) {
        this.entries = entries;
    }

    @Override
    @Nullable
    public <V> V get(ContextKey<V> key) {
        for (int i = 0; i < entries.length; i += 2) {
            if (entries[i] == key) {
                @SuppressWarnings("unchecked")
                V result = (V) entries[i + 1];
                return result;
            }
        }
        return null;
    }

    @Override
    public <V> XSContext with(ContextKey<V> key, V value) {
        for (int i = 0; i < entries.length; i += 2) {
            if (entries[i] == key) {
                if (entries[i + 1] == value) {
                    return this;
                }
                Object[] newEntries = entries.clone();
                newEntries[i + 1] = value;
                return new ReentryArrayBasedContext(newEntries);
            }
        }
        Object[] newEntries = Arrays.copyOf(entries, entries.length + 2);
        newEntries[newEntries.length - 2] = key;
        newEntries[newEntries.length - 1] = value;
        return new ReentryArrayBasedContext(newEntries);
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("{");
        for (int i = 0; i < entries.length; i += 2) {
            sb.append(entries[i]).append('=').append(entries[i + 1]).append(", ");
        }
        if (sb.length() > 1) {
            sb.setLength(sb.length() - 2);
        }
        sb.append('}');
        return sb.toString();
    }
}
